#include <amqpcpp.h>
#include <amqpcpp/libboostasio.h>
#include <boost/asio.hpp>
#include "libgo/coroutine.h"
#include "libzq/http/crow_all.h"
#include <boost/thread.hpp>
#include "libzq/service/protocol/jrpc.h"
#include "libzqutil/util.h"
#include "handler_impl.h"
#include "libzqutil/factory.h"
#include "libzqutil/hashlib.h"
#include <cpp_redis/cpp_redis>

bool check_sign(const crow::request& req)
{
	try
	{
		char* channel = req.url_params.get("channel");
		char* timestamp = req.url_params.get("timestamp");
		char* signature = req.url_params.get("signature");
		if (!channel || !timestamp || !signature)
		{
			return false;
		}
		int cur_timestamp = current_timestamp();
		if (abs(cur_timestamp - CAST_INT(timestamp)) > 60) return false;
		string sign_str = format("channel=%s&timestamp=%s%s", channel, timestamp, "58749c242c7f97efa7542b4eb9652e24");
		string sign = md5(sign_str);
		LOGT("sign_str: %s", sign_str);
		LOGT("sign: %s", sign);
		LOGT("check sign: %s", signature);
		return !sign.compare(signature);
	}
	catch (...)
	{
		return false;
	}
}
using namespace jrpc;
int main()
{
	CORE.install_signals();
	RedisSession::init("127.0.0.1", 6379);
	  
	App app;
	CROW_ROUTE(app, "/Session/Get")([&app](const crow::request& req)
	{
		auto& ctx = app.get_context<RedisSession>(req);
		return crow::response(ctx.get("uid"));
	});

	CROW_ROUTE(app, "/Session/Set")([&app](const crow::request& req)
	{
		auto& ctx = app.get_context<RedisSession>(req);
		ctx.set("uid", req.url_params.get("uid"));
		return crow::response(200);
	});

	CROW_ROUTE(app, "/Session/Del")([&app](const crow::request& req)
	{
		auto& ctx = app.get_context<RedisSession>(req);
		ctx.remove("uid");
		return crow::response(200);
	});

	CROW_ROUTE(app, "/Session/Clear")([&app](const crow::request& req)
	{
		auto& ctx = app.get_context<RedisSession>(req);
		ctx.clear();
		return crow::response(200);
	});

	CROW_ROUTE(app, "/Openapi/SchemeList")([&app](const crow::request& req)
	{
		if (!check_sign(req)) return crow::response(403);
		try
		{
			return Factory<HandlerImpl>::get().produce_shared("scheme.list")->handle(app, req);
		}
		catch (ProductNotFoundError)
		{
			return crow::response(404);
		}
	});

	CROW_ROUTE(app, "/Openapi/UserFee")([&app](const crow::request& req)
	{
		if (!check_sign(req)) return crow::response(403);
		try
		{
			return Factory<HandlerImpl>::get().produce_shared("account.fee")->handle(app, req);
		}
		catch (ProductNotFoundError)
		{
			return crow::response(404);
		}
	});

	CROW_ROUTE(app, "/Openapi/SchemeDetail")([&app](const crow::request& req)
	{
		if (!check_sign(req)) return crow::response(403);
		try
		{
			return Factory<HandlerImpl>::get().produce_shared("scheme.detail")->handle(app, req);
		}
		catch (ProductNotFoundError)
		{
			return crow::response(404);
		}
	});

	CROW_ROUTE(app, "/Openapi/IssueList")([&app](const crow::request& req)
	{
		if (!check_sign(req)) return crow::response(403);
		try
		{
			return Factory<HandlerImpl>::get().produce_shared("issue.list")->handle(app, req);
		}
		catch (ProductNotFoundError)
		{
			return crow::response(404);
		}
	});

	CROW_ROUTE(app, "/Openapi/IssueDetail")([&app](const crow::request& req)
	{
		if (!check_sign(req)) return crow::response(403);
		try
		{
			return Factory<HandlerImpl>::get().produce_shared("issue.detail")->handle(app, req);
		}
		catch (ProductNotFoundError)
		{
			return crow::response(404);
		}
	});

	JsonHttpFinder::instance().init("http://127.0.0.1:43330/server-finder/");
	app.port(43311).run();
	boost::thread_group tg;
	for (int i = 0; i < 8; ++i)
		tg.create_thread([] {
		co_sched.RunUntilNoTask();
	});
	tg.join_all();
}